package cn.dubito.miaosha.service;

import cn.dubito.miaosha.domain.OrderInfo;
import cn.dubito.miaosha.domain.SeckillOrder;
import cn.dubito.miaosha.domain.SeckillUser;
import cn.dubito.miaosha.redis.RedisService;
import cn.dubito.miaosha.redis.SeckillKey;
import cn.dubito.miaosha.utils.MD5Util;
import cn.dubito.miaosha.utils.UUIDUtil;
import cn.dubito.miaosha.vo.GoodsVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;

/**
 * @author liliang
 * @description:
 * @date 2018/3/31.
 */
@Service
public class SeckillService {

    private static final int ISOVER = -1;
    private static final int WAIT = 0;

    @Autowired
    private GoodsService goodsService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private RedisService redisService;

    @Transactional(rollbackFor = Exception.class)
    public OrderInfo seckill(SeckillUser user, GoodsVO goods) {
        boolean success = goodsService.reduceStock(goods);
        if (success) {
            return orderService.createOrder(user, goods);
        }
        setGoodsOver(goods.getId());
        return null;
    }

    /**
     * 获取结果
     *
     * @param userId
     * @param goodsId
     * @return
     */
    public long getSeckillResult(Long userId, long goodsId) {
        SeckillOrder order = orderService.getSeckillOrderByUserIdAndGoodsId(userId, goodsId);
        if (order != null) {
            return order.getOrderId();
        }
        boolean isOver = getGoodsOver(goodsId);
        if (isOver) {
            return ISOVER;
        }
        return WAIT;
    }

    /**
     * 获取结果
     *
     * @param goodsId
     * @return
     */
    private boolean getGoodsOver(Long goodsId) {
        return redisService.exist(SeckillKey.isOver, String.valueOf(goodsId));
    }

    /**
     * 设置结果
     *
     * @param goodsId
     */
    private void setGoodsOver(Long goodsId) {
        redisService.set(SeckillKey.isOver, String.valueOf(goodsId), true);
    }

    /**
     * 校验秒杀路径
     *
     * @param path
     * @param user
     * @return
     */
    public boolean checkPath(String path, SeckillUser user, long goodsId) {
        if (user == null || path == null) {
            return false;
        }
        String pathOld = redisService.get(SeckillKey.getSeckillPath, String.valueOf(user.getId()) + "_" + String.valueOf(goodsId), String.class);
        return path.equals(pathOld);
    }


    /**
     * 生成秒杀路径
     *
     * @param user
     * @param goodsId
     * @return
     */
    public String createSeckillPath(SeckillUser user, long goodsId) {
        if (user == null || goodsId <= 0) {
            return null;
        }
        String str = MD5Util.md5(UUIDUtil.uuid() + "asdfg");
        redisService.set(SeckillKey.getSeckillPath, String.valueOf(user.getId()) + "_" + String.valueOf(goodsId), str);
        return str;
    }


    /**
     * 生成图片验证码
     *
     * @param user
     * @param goodsId
     * @return
     */
    public BufferedImage createVerifyCodeImage(SeckillUser user, long goodsId) {
        if (user == null || goodsId <= 0) {
            return null;
        }

        int width = 120;
        int height = 32;

        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics g = image.getGraphics();
        g.setColor(new Color(0xDCDCDC));
        g.fillRect(0, 0, width, height);
        g.setColor(Color.BLACK);
        g.drawRect(0, 0, width - 1, height - 1);

        Random random = new Random();
        for (int i = 0; i < 50; i++) {
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            g.drawOval(x, y, 0, 0);
        }

        String verifyCode = createVerifyCode(random);
        g.setColor(new Color(53, 100, 180));
        g.setFont(new Font("Candara", Font.BOLD, 22));
        g.drawString(verifyCode + "= ?", 8, 22);
        g.dispose();

        // 保存 code 到 redis 中
        int result = calc(verifyCode);
        redisService.set(SeckillKey.getSeckillVerifyCode, user.getId() + "_" + goodsId, result);

        return image;
    }


    /**
     * 计算结果
     *
     * @param exp
     * @return
     */
    private int calc(String exp) {
        try {
            ScriptEngineManager manager = new ScriptEngineManager();
            ScriptEngine engine = manager.getEngineByName("JavaScript");
            return (Integer) engine.eval(exp);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * + - *
     *
     * @param random
     * @return
     */
    private String createVerifyCode(Random random) {
        char[] ops = new char[]{'+', '-', '*'};
        int num1 = random.nextInt(10);
        int num2 = random.nextInt(10);
        int num3 = random.nextInt(10);
        char op1 = ops[random.nextInt(3)];
        char op2 = ops[random.nextInt(3)];
        return "" + num1 + op1 + num2 + op2 + num3;
    }

    public static void main(String[] args) {
        SeckillService service = new SeckillService();
        String verifyCode = service.createVerifyCode(new Random());
        int calc = service.calc(verifyCode);
        System.out.println(verifyCode);
        System.out.println(calc);
    }

    /**
     * 验证 code 验证码
     * @param user
     * @param goodsId
     * @param verifyCode
     * @return
     */
    public boolean checkCode(SeckillUser user, long goodsId, int verifyCode) {
        if (user == null || goodsId <= 0) {
            return  false;
        }
        Integer code = redisService.get(SeckillKey.getSeckillVerifyCode, user.getId() + "_" + goodsId, Integer.class);
        if (code == null || code - verifyCode != 0) {
            return false;
        }
        redisService.delete(SeckillKey.getSeckillVerifyCode, user.getId() + "_" + goodsId);
        return code.equals(verifyCode);
    }
}
